From 618d247ec86f7b407a4f249132f8439d5c1103a3 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 14 Mar 2007 10:44:56 +0000 Subject: [PATCH] add usb device save/restore in qemu Signed-off-by: Zhai Edwin --- tools/ioemu/hw/usb-hid.c | 47 ++++++++++++++++++++++++++++++++++++++ tools/ioemu/hw/usb-ohci.c | 2 ++ tools/ioemu/hw/usb-uhci.c | 48 +++++++++++++++++++++++++++++++++++++++ tools/ioemu/hw/usb.c | 40 ++++++++++++++++++++++++++++++++ tools/ioemu/hw/usb.h | 6 +++++ tools/ioemu/vl.c | 19 ++++++++++++++++ 6 files changed, 162 insertions(+) diff --git a/tools/ioemu/hw/usb-hid.c b/tools/ioemu/hw/usb-hid.c index 60849a4ed0..c7af3d65ab 100644 --- a/tools/ioemu/hw/usb-hid.c +++ b/tools/ioemu/hw/usb-hid.c @@ -517,6 +517,49 @@ static void usb_mouse_handle_destroy(USBDevice *dev) qemu_free(s); } +void usb_mouse_save(QEMUFile *f, void *opaque) +{ + USBMouseState *s = (USBMouseState*)opaque; + + qemu_put_be32s(f, &s->dx); + qemu_put_be32s(f, &s->dy); + qemu_put_be32s(f, &s->dz); + qemu_put_be32s(f, &s->buttons_state); + qemu_put_be32s(f, &s->x); + qemu_put_be32s(f, &s->y); + qemu_put_be32s(f, &s->kind); + qemu_put_be32s(f, &s->mouse_grabbed); + qemu_put_be32s(f, &s->status_changed); + +} + +int usb_mouse_load(QEMUFile *f, void *opaque, int version_id) +{ + USBMouseState *s = (USBMouseState*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &s->dx); + qemu_get_be32s(f, &s->dy); + qemu_get_be32s(f, &s->dz); + qemu_get_be32s(f, &s->buttons_state); + qemu_get_be32s(f, &s->x); + qemu_get_be32s(f, &s->y); + qemu_get_be32s(f, &s->kind); + qemu_get_be32s(f, &s->mouse_grabbed); + qemu_get_be32s(f, &s->status_changed); + + if ( s->kind == USB_TABLET) { + fprintf(logfile, "usb_mouse_load:add usb_tablet_event.\n"); + qemu_add_mouse_event_handler(usb_tablet_event, s, 1); + } else if ( s->kind == USB_MOUSE) { + fprintf(logfile, "usb_mouse_load:add usb_mouse_event.\n"); + qemu_add_mouse_event_handler(usb_mouse_event, s, 0); + } +} + + USBDevice *usb_tablet_init(void) { USBMouseState *s; @@ -536,6 +579,8 @@ USBDevice *usb_tablet_init(void) pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet"); + register_savevm("USB tablet dev", 0, 1, usb_mouse_save, usb_mouse_load, s); + return (USBDevice *)s; } @@ -558,5 +603,7 @@ USBDevice *usb_mouse_init(void) pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse"); + register_savevm("USB mouse dev", 0, 1, usb_mouse_save, usb_mouse_load, s); + return (USBDevice *)s; } diff --git a/tools/ioemu/hw/usb-ohci.c b/tools/ioemu/hw/usb-ohci.c index e87d9da70a..a563262676 100644 --- a/tools/ioemu/hw/usb-ohci.c +++ b/tools/ioemu/hw/usb-ohci.c @@ -1186,5 +1186,7 @@ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn) qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach); } + register_savevm("OHCI USB", 0, 1, generic_pci_save, generic_pci_load, ohci); + ohci_reset(ohci); } diff --git a/tools/ioemu/hw/usb-uhci.c b/tools/ioemu/hw/usb-uhci.c index 7212c5e82d..46cff274cf 100644 --- a/tools/ioemu/hw/usb-uhci.c +++ b/tools/ioemu/hw/usb-uhci.c @@ -658,6 +658,50 @@ static void uhci_map(PCIDevice *pci_dev, int region_num, register_ioport_read(addr, 32, 1, uhci_ioport_readb, s); } +void uhci_usb_save(QEMUFile *f, void *opaque) +{ + int i; + UHCIState *s = (UHCIState*)opaque; + + qemu_put_be16s(f, &s->cmd); + qemu_put_be16s(f, &s->status); + qemu_put_be16s(f, &s->intr); + qemu_put_be16s(f, &s->frnum); + qemu_put_be32s(f, &s->fl_base_addr); + qemu_put_8s(f, &s->sof_timing); + qemu_put_8s(f, &s->status2); + + for(i = 0; i < NB_PORTS; i++) { + qemu_put_be16s(f, &s->ports[i].ctrl); + } + + qemu_put_timer(f, s->frame_timer); +} + +int uhci_usb_load(QEMUFile *f, void *opaque, int version_id) +{ + int i; + UHCIState *s = (UHCIState*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be16s(f, &s->cmd); + qemu_get_be16s(f, &s->status); + qemu_get_be16s(f, &s->intr); + qemu_get_be16s(f, &s->frnum); + qemu_get_be32s(f, &s->fl_base_addr); + qemu_get_8s(f, &s->sof_timing); + qemu_get_8s(f, &s->status2); + + for(i = 0; i < NB_PORTS; i++) { + qemu_get_be16s(f, &s->ports[i].ctrl); + } + + qemu_get_timer(f, s->frame_timer); + +} + void usb_uhci_init(PCIBus *bus, int devfn) { UHCIState *s; @@ -693,4 +737,8 @@ void usb_uhci_init(PCIBus *bus, int devfn) to rely on this. */ pci_register_io_region(&s->dev, 4, 0x20, PCI_ADDRESS_SPACE_IO, uhci_map); + + register_savevm("UHCI_usb_pci", 0, 1, generic_pci_save, generic_pci_load, s); + + register_savevm("UHCI usb controller", 0, 1, uhci_usb_save, uhci_usb_load, s); } diff --git a/tools/ioemu/hw/usb.c b/tools/ioemu/hw/usb.c index 34aac5fa9b..e4166518b0 100644 --- a/tools/ioemu/hw/usb.c +++ b/tools/ioemu/hw/usb.c @@ -191,3 +191,43 @@ int set_usb_string(uint8_t *buf, const char *str) } return q - buf; } + +void generic_usb_save(QEMUFile* f, void *opaque) +{ + USBDevice *s = (USBDevice*)opaque; + + qemu_put_be32s(f, &s->speed); + qemu_put_8s(f, &s->addr); + qemu_put_be32s(f, &s->state); + + qemu_put_buffer(f, s->setup_buf, 8); + qemu_put_buffer(f, s->data_buf, 1024); + + qemu_put_be32s(f, &s->remote_wakeup); + qemu_put_be32s(f, &s->setup_state); + qemu_put_be32s(f, &s->setup_len); + qemu_put_be32s(f, &s->setup_index); + +} + +int generic_usb_load(QEMUFile* f, void *opaque, int version_id) +{ + USBDevice *s = (USBDevice*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &s->speed); + qemu_get_8s(f, &s->addr); + qemu_get_be32s(f, &s->state); + + qemu_get_buffer(f, s->setup_buf, 8); + qemu_get_buffer(f, s->data_buf, 1024); + + qemu_get_be32s(f, &s->remote_wakeup); + qemu_get_be32s(f, &s->setup_state); + qemu_get_be32s(f, &s->setup_len); + qemu_get_be32s(f, &s->setup_index); + + return 0; +} diff --git a/tools/ioemu/hw/usb.h b/tools/ioemu/hw/usb.h index 98fde06569..9df69f8dc8 100644 --- a/tools/ioemu/hw/usb.h +++ b/tools/ioemu/hw/usb.h @@ -176,3 +176,9 @@ USBDevice *usb_tablet_init(void); /* usb-msd.c */ USBDevice *usb_msd_init(const char *filename); + +/* usb.c */ +void generic_usb_save(QEMUFile* f, void *opaque); +int generic_usb_load(QEMUFile* f, void *opaque, int version_id); + + diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 0b78fa8650..6f9219fa40 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -841,10 +841,22 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) #ifdef CONFIG_DM static void timer_save(QEMUFile *f, void *opaque) { + /* need timer for save/restoe qemu_timer in usb_uhci */ + if (cpu_ticks_enabled) { + hw_error("cannot save state if virtual timers are running"); + } + qemu_put_be64s(f, &cpu_clock_offset); } static int timer_load(QEMUFile *f, void *opaque, int version_id) { + if (version_id != 1) + return -EINVAL; + if (cpu_ticks_enabled) { + return -EINVAL; + } + + qemu_get_be64s(f, &cpu_clock_offset); return 0; } #else /* !CONFIG_DM */ @@ -3900,6 +3912,7 @@ static int usb_device_add(const char *devname) const char *p; USBDevice *dev; USBPort *port; + char usb_name[256] = "USB "; if (!free_usb_ports) return -1; @@ -3936,6 +3949,12 @@ static int usb_device_add(const char *devname) free_usb_ports = port->next; port->next = used_usb_ports; used_usb_ports = port; + + pstrcpy(usb_name + strlen(usb_name), + sizeof(usb_name) - strlen(usb_name), + devname); + register_savevm(usb_name, 0, 1, generic_usb_save, generic_usb_load, dev); + usb_attach(port, dev); return 0; } -- 2.30.2